package org.uned.agonzalo16.bitacora.web.user;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.uned.agonzalo16.bitacora.dao.MessageDao;
import org.uned.agonzalo16.bitacora.dao.UserDao;
import org.uned.agonzalo16.bitacora.domain.User;
import org.uned.agonzalo16.bitacora.domain.UserType;

@RequestMapping("/user")
@Controller
public class UserController {

	private static final Logger logger = Logger.getLogger(UserController.class);

	@Autowired
	private UserDao userDao;

	@Autowired
	private MessageDao messageDao;

	@RequestMapping(method = RequestMethod.GET, value = "/forgetPassword")
	public ResponseEntity<String> forgetPassword(@RequestParam("email") String email) {

		HttpHeaders responseHeaders = new HttpHeaders();
		responseHeaders.add("Content-Type", "text/plain; charset=utf-8");

		// obtener el usuario al que pertenece el mail
		User user = findByEmail(email.trim());

		if (user == null) {
			return new ResponseEntity<String>("{\"status\": \"noUser\"}", responseHeaders, HttpStatus.CREATED);
		}

		// cambiar password
		String newPassword = generatePassword();
		user.setPassword(newPassword);

		// enviar mail
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		String msgBody = "Hola, esta es tu nueva contraseña para la aplicación: " + newPassword;

		try {
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("angel.gonzalo.martin@gmail.com", "Distance Blogs - Admin"));
			msg.addRecipient(Message.RecipientType.TO, new InternetAddress(email, user.getUsername()));
			msg.setSubject("Nueva password");
			msg.setText(msgBody);
			Transport.send(msg);

			userDao.merge(user);

		} catch (AddressException e) {
			logger.error("AddressException: " + e.getMessage());
			return new ResponseEntity<String>("{\"status\": \"error\"}", responseHeaders, HttpStatus.CREATED);
		} catch (MessagingException e) {
			logger.error("MessagingException: " + e.getMessage());
			return new ResponseEntity<String>("{\"status\": \"error\"}", responseHeaders, HttpStatus.CREATED);
		} catch (UnsupportedEncodingException e) {
			logger.error("UnsupportedEncodingException: " + e.getMessage());
			return new ResponseEntity<String>("{\"status\": \"error\"}", responseHeaders, HttpStatus.CREATED);
		}

		// devolver ok
		return new ResponseEntity<String>("{\"status\": \"ok\"}", responseHeaders, HttpStatus.CREATED);
	}

	private User findByEmail(String email) {
		for (User user : userDao.findAll()) {
			if (user.getEmail().equals(email)) {
				return user;
			}
		}
		return null;
	}

	private String generatePassword() {
		return RandomStringUtils.random(8, true, true);
	}

	@RequestMapping(method = RequestMethod.GET, value = "/register")
	public ResponseEntity<String> register(@RequestParam("email") String email, @RequestParam("nick") String nick, @RequestParam("type") String type) {

		HttpHeaders responseHeaders = new HttpHeaders();
		responseHeaders.add("Content-Type", "text/plain; charset=utf-8");

		// validar que el email no está en uso
		if (findByEmail(email.trim()) != null) {
			return new ResponseEntity<String>("{\"status\": \"duplicateEmail\"}", responseHeaders, HttpStatus.CREATED);
		}

		// validar que el nick no está en uso
		if (userDao.findByUsername(nick.trim()) != null) {
			return new ResponseEntity<String>("{\"status\": \"duplicateNick\"}", responseHeaders, HttpStatus.CREATED);
		}

		// buscar un administrador
		User admin = findAdmin();

		if (admin == null) {
			return new ResponseEntity<String>("{\"status\": \"noAdmin\"}", responseHeaders, HttpStatus.CREATED);
		}

		// enviar un mensaje privado con los datos de registro
		org.uned.agonzalo16.bitacora.domain.Message msg = new org.uned.agonzalo16.bitacora.domain.Message();
		msg.setSubject("Solicitud de registro");
		msg.setContent("Email: " + email + ", nombre de usuario: " + nick + ", tipo de usuario: " + type);
		msg.setCreationDate(new Date());
		msg.setDestination(admin);
		msg.setOrigin(admin);
		messageDao.merge(msg);

		// devolver ok
		return new ResponseEntity<String>("{\"status\": \"ok\"}", responseHeaders, HttpStatus.CREATED);
	}

	private User findAdmin() {
		for (User user : userDao.findAll()) {
			if (user.getType() == UserType.ADMIN.getType()) {
				return user;
			}
		}
		return null;
	}

}
